import sys
import os
import time
import subprocess
from PyQt6.QtWidgets import (
    QApplication, QMainWindow, QSplitter, QTreeView, QTabWidget, QStatusBar, 
    QVBoxLayout, QWidget, QTextEdit, QGraphicsView, QGraphicsScene, QGraphicsRectItem,
    QToolBar, QMessageBox, QPushButton, QLabel, QMenu, 
    QInputDialog, QFileDialog, QDialog, QDialogButtonBox, QSizePolicy
)
from PyQt6.QtGui import (
    QIcon, QTextCharFormat, QColor, QFont, QPen, QBrush, QPainterPath, QFileSystemModel,
    QTextCursor, QPalette, QStandardItemModel, QStandardItem, QSyntaxHighlighter, 
    QRegularExpressionValidator, QAction, QPainter
)
from PyQt6.QtCore import (
    Qt, QRectF, QPointF, QModelIndex, QFileInfo, QSortFilterProxyModel,
    QRegularExpression, QTimer, QSize
)
import git
from git import Repo, GitCommandError, InvalidGitRepositoryError





# ===================== 提交历史可视化 =====================
class HistoryGraphWidget(QGraphicsView):
    NODE_WIDTH = 250
    NODE_HEIGHT = 80
    NODE_SPACING = 50
    LANE_SPACING = 100
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.scene = QGraphicsScene(self)
        self.setScene(self.scene)
        self.setRenderHints(QPainter.RenderHint.Antialiasing | 
                            QPainter.RenderHint.TextAntialiasing | 
                            QPainter.RenderHint.SmoothPixmapTransform)
        
        # 设置背景为深色
        self.setBackgroundBrush(QBrush(QColor("#252526")))
        
        # 节点布局数据
        self.nodes = {}
        self.positions = {}
        self.commit_nodes = {}
    
    def draw_history(self, graph_data):
        self.scene.clear()
        self.nodes = {}
        self.positions = {}
        self.commit_nodes = {}
        
        if not graph_data['nodes']:
            return
        
        # 拓扑排序确定节点位置
        self.layout_graph(graph_data)
        
        # 首先绘制边
        for edge in graph_data['edges']:
            self.draw_edge(edge['source'], edge['target'], edge.get('merge', False))
        
        # 然后绘制节点（在顶部）
        for node in graph_data['nodes']:
            if node['id'] in self.positions:
                x, y = self.positions[node['id']]
                self.draw_commit_node(node, x, y)
    
    def layout_graph(self, graph_data):
        """使用分层布局算法确定节点位置"""
        # 1. 计算每个节点的深度
        node_depths = {}
        for node in graph_data['nodes']:
            node_depths[node['id']] = 0
            
        changed = True
        while changed:
            changed = False
            for edge in graph_data['edges']:
                src_depth = node_depths.get(edge['source'], 0)
                tgt_depth = node_depths[edge['target']]
                if tgt_depth <= src_depth:
                    node_depths[edge['target']] = src_depth + 1
                    changed = True
        
        # 2. 根据深度分组
        depth_groups = {}
        max_depth = 0
        for node in graph_data['nodes']:
            depth = node_depths[node['id']]
            max_depth = max(max_depth, depth)
            if depth not in depth_groups:
                depth_groups[depth] = []
            depth_groups[depth].append(node['id'])
        
        # 3. 在每层中排序节点
        depth_positions = {}
        for depth in range(max_depth + 1):
            depth_positions[depth] = 0
        
        # 4. 分配位置
        for depth in sorted(depth_groups.keys()):
            group = depth_groups[depth]
            lane = 0
            for node_id in group:
                x = depth * self.LANE_SPACING + 50
                y = lane * (self.NODE_HEIGHT + self.NODE_SPACING) + 50
                self.positions[node_id] = (x, y)
                lane += 1
                depth_positions[depth] = max(depth_positions[depth], lane)
    
    def draw_commit_node(self, node, x, y):
        """绘制提交节点"""
        # 节点背景（HEAD节点使用不同颜色）
        if node.get('is_head', False):
            color = QColor("#4ec9b0")
        elif node['tags']:
            color = QColor("#d7ba7d")
        else:
            color = QColor("#007acc")
        
        node_rect = QRectF(x, y, self.NODE_WIDTH, self.NODE_HEIGHT)
        bg_item = self.scene.addRect(node_rect, QPen(color.darker(120), 2), 
                                     QBrush(color.darker(150)))
        bg_item.setZValue(1)
        
        # 添加文本
        header = f"┏ {node['id']}" + (f" ({', '.join(node['tags'])})" if node['tags'] else "")
        header_text = self.scene.addText(header)
        header_text.setPos(x + 10, y + 5)
        header_text.setDefaultTextColor(QColor("#ffffff"))
        header_text.setZValue(2)
        
        message_text = self.scene.addText(node['message'])
        message_text.setPos(x + 15, y + 25)
        message_text.setDefaultTextColor(QColor("#dcdcaa"))  # 黄色
        message_text.setZValue(2)
        
        author_text = self.scene.addText(f"👤 {node['author']}")
        author_text.setPos(x + 15, y + 50)
        author_text.setDefaultTextColor(QColor("#b4b4b4"))
        author_text.setZValue(2)
        
        # 存储节点引用
        self.commit_nodes[node['id']] = bg_item
    
    def draw_edge(self, source_id, target_id, is_merge=False):
        """在两个提交之间绘制边线"""
        if source_id not in self.positions or target_id not in self.positions:
            return
        
        src_x, src_y = self.positions[source_id]
        tgt_x, tgt_y = self.positions[target_id]
        
        src_center_x = src_x + self.NODE_WIDTH / 2
        src_center_y = src_y + self.NODE_HEIGHT
        tgt_center_x = tgt_x + self.NODE_WIDTH / 2
        tgt_center_y = tgt_y
        
        # 创建路径
        path = QPainterPath(QPointF(src_center_x, src_center_y))
        
        # 计算控制点
        ctrl_offset = (tgt_x - src_x) / 3
        
        path.cubicTo(
            src_center_x, src_center_y + ctrl_offset,
            tgt_center_x, tgt_center_y - ctrl_offset,
            tgt_center_x, tgt_center_y
        )
        
        # 设置边线样式
        pen = QPen(QColor("#569cd6"), 2)
        pen.setStyle(Qt.PenStyle.DashLine if is_merge else Qt.PenStyle.SolidLine)
        self.scene.addPath(path, pen)


